<?php

namespace TpAmis\Plugin\FormBuilder;

use TpAmis\Renderers\Amis;
use TpAmis\Renderers\BaseApi;
use TpAmis\Renderers\BaseRenderer;
use TpAmis\Traits\BaseApiTrait;
use TpAmis\Traits\ButtonsTrait;
use TpAmis\util\AmisConfig;

class FormBuilder extends BaseRenderer
{
    use BaseApiTrait;
    use ButtonsTrait;

    protected array $body = [];
    protected array $data = [];
    protected object $amis;
    protected string $primaryKey = 'id';
    protected bool $is_filter = false;


    public function __construct()
    {
        $this->amis = amis()->Form();

        $this->setApi($this->BaseApiPost('index'));
    }
    public function isFilter()
    {
        $this->is_filter = true;
        return $this;
    }

    public static function make()
    {
        return new self();
    }
    public function amis()
    {
        return $this->amis;
    }

    public function set($name, $value)
    {
        $this->amis->set($name, $value);
        return $this;
    }
    public function setTitle($value)
    {
        $this->amis->set('title', $value);
        return $this;
    }
    protected BaseApi $api;

    /**
     * @param BaseApi $api
     * @return $this
     */
    public function setApi(BaseApi $api): FormBuilder
    {
        $this->api = $api;
        return $this;
    }
    public function debug(): FormBuilder
    {
        $this->amis->debug(true);
        return $this;
    }

    public function unset($type)
    {
        $this->amis->unset('type');
        return $this;
    }

    public function redirect() {}


    /**
     * 设置表单数据
     * @param mixed $data
     * @return $this
     */
    public function data($data = []): FormBuilder
    {
        $this->data = $data;
        return $this;
    }


    protected array $actions = [];

    /**
     * 设置表单按钮
     * @param string $label 按钮名称
     * @param string $type 按钮类型
     * @param array $extend_attr 扩展属性
     * @return $this
     */
    public function setActions($label = '', $type = '', $extend_attr = [])
    {
        $items = amis()->Action()->label($label)->actionType($type);
        $this->extend_attr($items, $extend_attr);
        $this->actions[] = $items;
        return $this;
    }

    /**
     * 设置提交按钮
     * @param string $label 按钮名称
     * @param array $extend_attr 扩展属性
     * @param string $url 请求地址
     * @param array $vars 请求参数
     * @param bool $suffix 是否添加后缀
     * @param bool $domain 是否添加域名
     * @return $this
     */
    public function setSubmitAction($label = '保存', $extend_attr = [], $url = '', array $vars = [], $data = [], $type = 'form')
    {
        if (is_object($label)) {
            $items = $label;
        } else {
            if (is_string($url)) {
                if (! $this->containsAny($url, ['get:', 'post:', 'put:', 'delete:'])) {
                    $url = $this->BaseApiPost($url, [$vars], $data, $type);
                }
            }

            $items = amis()->Action()->label($label)->actionType('ajax')->api($url);
        }
        $this->extend_attr($items, $extend_attr);
        $this->actions[] = $items;
        return $this;
    }

    public function setFilterSubmitAction()
    {
        $this->actions[] = ["type" => "submit", "label" => "查询", 'level' => 'primary'];
        return $this;
    }
    public function setResetAction()
    {
        $this->actions[] = ["type" => "reset", "label" => "重置", 'level' => 'primary'];
        return $this;
    }
    private function containsAny($string, $array)
    {
        foreach ($array as $value) {
            if (strpos($string, $value) !== false) {
                return true;
            }
        }
        return false;
    }

    private function buildBody()
    {

        $items = [];
        foreach ($this->body as $body) {
            if (is_object($body)) {
                $items[] = $body;
            } else {
                $item = $this->CheckType($body);
                if ($item) {
                    if (count($body) > 6) {
                        $body = array_slice($body, 6);
                        if (isset($body)) {
                            foreach ($body as $key => $value) {
                                $item->set($key, $value);
                            }
                        }
                    }
                    $items[] = $item;
                }
            }
        }
        return $items;
    }
    private function CheckType($item)
    {
        $name = $this->is_filter ? $item['name'] . '$filter|' . $item['type'] : $item['name'];

        switch ($item['type']) {
            case 'type':
            case 'radios':
            case 'status':
                $items = amis()->RadiosControl($name, $item['label']);
                break;
            case 'select':
                $items = amis()->SelectControl($name, $item['label'])->searchable();
                break;
            case 'image':
            case 'avatar':
                $items = amis()->ImageControl($name, $item['label']);
                break;
            case 'switch':
                $items = amis()->SwitchControl($name, $item['label'])->trueValue(1)->falseValue(0);
                break;
            case 'time':
                if ($this->is_filter) {
                    $items = amis()->TimeRangeControl($name, $item['label']);
                } else {
                    $items = amis()->TimeControl($name, $item['label']);
                }
                break;
            case 'timeRange':
                $items = amis()->TimeRangeControl($name, $item['label']);
                break;
            case 'date':
                if ($this->is_filter) {
                    $items = amis()->DateRangeControl($name, $item['label']);
                } else {
                    $items = amis()->DateControl($name, $item['label']);
                }
                break;
            case 'dateRange':
                $items = amis()->DateRangeControl($name, $item['label']);
                break;
            case 'datetime':
                if ($this->is_filter) {
                    $items = amis()->DateTimeRangeControl($name, $item['label']);
                } else {
                    $items = amis()->DateTimeControl($name, $item['label']);
                }
                break;
            case 'datetimeRange':
                $items = amis()->DateTimeRangeControl($name, $item['label']);
                break;
            case 'month':
                if ($this->is_filter) {
                    $items = amis()->MonthRangeControl($name, $item['label']);
                } else {
                    $items = amis()->MonthControl($name, $item['label']);
                }
                break;
            case 'monthRange':
                $items = amis()->MonthRangeControl($name, $item['label']);
                break;
            case 'quarter':
                if ($this->is_filter) {
                    $items = amis()->QuarterRangeControl($name, $item['label']);
                } else {
                    $items = amis()->QuarterControl($name, $item['label']);
                }
                break;
            case 'quarterRange':
                $items = amis()->QuarterRangeControl($name, $item['label']);
                break;
            case 'year':
                if ($this->is_filter) {
                    $items = amis()->YearRangeControl($name, $item['label']);
                } else {
                    $items = amis()->YearControl($name, $item['label']);
                }
                break;
            case 'yearRange':
                $items = amis()->YearRangeControl($name, $item['label']);
                break;
            case 'condition-builder':
                $items = amis()->ConditionBuilderControl($name, $item['label']);
                if (isset($item['default'])) {
                    $items->fields($item['default']);
                }

                break;
            case 'file':
                $items = amis()->FileControl($name, $item['label']);
                if (isset($item['options']['receiver'])) {
                    $items->receiver($item['options']['receiver']);
                } else {
                    $items->receiver(AmisConfig::get('upload_api') ?? '');
                }
                if (isset($item['options']['accept'])) {
                    $items->accept($item['options']['accept']);
                } else {
                    $items->accept(AmisConfig::get('accept') ?? '');
                }
                $items->useChunk(false)->asBlob(true);
                break;
            case 'file_api':
                $items = amis()->FileControl($name, $item['label']);
                if (isset($item['options']['receiver'])) {
                    $items->receiver($item['options']['receiver']);
                } else {
                    $items->receiver(AmisConfig::get('upload_api') ?? '');
                }

                if (isset($item['options']['accept'])) {
                    $items->accept($item['options']['accept']);
                } else {
                    $items->accept(AmisConfig::get('accept') ?? '');
                }
                $items->useChunk(false);
                break;
            case 'file_chunk':
                $items = amis()->FileControl($name, $item['label']);
                if (isset($item['options']['receiver'])) {
                    $items->receiver($item['options']['receiver']);
                } else {
                    $items->receiver(AmisConfig::get('upload_api') ?? '');
                }

                if (isset($item['options']['accept'])) {
                    $items->accept($item['options']['accept']);
                } else {
                    $items->accept(AmisConfig::get('accept') ?? '');
                }
                if (!isset($item['options']['asBlob']) || $item['options']['asBlob'] == false) {
                    $items->asBlob(true);
                }
                // useChunk

                $items->useChunk(true);
                $items->chunkSize(AmisConfig::get('chunk_size') ?? 1024 * 1024 * 2);
                $items->startChunkApi(AmisConfig::get('start_chunk_api') ?? '');
                $items->chunkApi(AmisConfig::get('chunk_api') ?? '');
                $items->finishChunkApi(AmisConfig::get('finish_chunk_api') ?? '');
                $items->concurrency(AmisConfig::get('concurrency') ?? '');

                break;
            default:
                $type = ucfirst(strtolower($item['type'])) . 'Control';
                $items = amis()->$type($name, $item['label']);
        }
        // dump($item['type']);die;
        // if (!$this->is_filter) {

        if (in_array($item['type'], ['select', 'radios', 'checkboxs', 'status'])) {

            if (is_array($item['default'])) {
                $items->set('options', $item['default']);
            } else {
                $items->set('value', $item['default']);
                $items->set('options', $item['options']);
            }
        } else {
            // $items->set('options', $item['options']);
            $items->set('value', $item['default']);
            if (is_array($item['options'])) {
                foreach ($item['options'] as $key => $value) {
                    $items->set($key, $value);
                }
            }
        }
        // }

        $items->placeholder('输入' . $item['label'])->description($item['description'])->clearable();
        return $items;
    }
    public function filteredResults(): array
    {
        $this->amis->api($this->api);
        if (! empty($this->data)) {
            $this->amis->data($this->data);
        }
        $this->amis->body($this->buildBody());
        if (!empty($this->actions)) {
            $this->amis->actions($this->actions);
        }
        return $this->amis->toArray();
    }


    /**
     * 查询表单设置
     * @param string $name 字段名称
     * @param string $label 字段标签
     * @param string $type 字段类型
     * @param mixed $description 字段描述
     * @param mixed $default 默认值
     * @param array $options 选项
     * @param mixed $attr 属性
     * @return static
     */
    public function addFormItem($name = '', string $label = '', string $type = 'text', $description = '', $default = '', array $options = [], $attr = []): FormBuilder
    {

        if (is_object($name)) {
            $this->body[] =  $name;
        } else {
            $type = strtolower($type);
            $items = [
                'name' => $name,
                'label' => $label,
                'type' => $type,
                'description' => $description,
                'default' => $default,
                'options' => $options,
            ];
            // $args  = array_slice(func_get_args(), 7);
            $args  = array_merge($items,  $attr);

            $this->body[] = $args;
        }
        return $this;
    }

    protected function extend_attr(&$items, array $extend_attr = [])
    {
        foreach ($extend_attr as $key => $value) {
            $items->set($key, $value);
        }
        return $items;
    }

    /**
     * 批量添加表单项
     * @param array $items
     * @return $this
     */
    public function addFormItems(array $items = []): FormBuilder
    {
        if (!empty($items)) {
            foreach ($items as $options) {
                call_user_func_array([$this, 'addFormItem'], $options);
            }
        }
        return $this;
    }

    public function __call($name, $arguments)
    {
        if (strpos($name, 'add') !== false) {
            $type = $name;
            $type = str_replace('add', '', $type);

            $type = strtolower($type);

            $items = [
                'name' => isset($arguments[0]) ? $arguments[0] : '',
                'label' => isset($arguments[1]) ? $arguments[1] : '',
                'type' => $type,
                'description' => isset($arguments[2]) ? $arguments[2] : '',
                'default' => isset($arguments[3]) ? $arguments[3] : '',
                'options' => isset($arguments[4]) ? $arguments[4] : [],
            ];

            $args = array_slice($arguments, 5);
            $args = array_merge($items, $args);
            $this->addFormItem(...$args);
        }
        if (strpos($name, 'set') !== false) {

            $name = str_replace('set', '', $name);
            $name = lcfirst($name);

            $this->amis->set($name, ...$arguments);
        }

        return $this;
    }
}
